/*
 * Copyright (C) 2012 YIXIA.COM
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.mediacenter.activity;

import io.vov.vitamio.utils.VP;
import io.vov.vitamio.widget.MediaController;
import io.vov.vitamio.widget.OutlineTextView;
import io.vov.vitamio.widget.VideoView;

import java.io.File;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.KeyguardManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnCancelListener;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.media.AudioManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.BatteryManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.text.TextUtils;
import android.view.SurfaceHolder;
import android.view.View;
import android.view.ViewGroup.MarginLayoutParams;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.mediacenter.R;
import com.mediacenter.application.MApplication;
import com.mediacenter.site.model.Show;
import com.mediacenter.site.model.Video;
import com.mediacenter.site.model.VideoPath;
import com.mediacenter.widget.ProgressManager;
import com.naduolai.android.ui.dialog.StandardAlertDialog;
import com.naduolai.android.util.StringUtil;
import com.ndjh.ormlite.NDJHBaseDao;
import com.umeng.analytics.MobclickAgent;
import com.yixia.zi.provider.Session;
import com.yixia.zi.utils.BitmapHelper;
import com.yixia.zi.utils.FileHelper;
import com.yixia.zi.utils.FileUtils;
import com.yixia.zi.utils.Log;
import com.yixia.zi.utils.Media;
import com.yixia.zi.utils.StringHelper;
import com.yixia.zi.utils.ToastHelper;
import com.yixia.zi.utils.UIUtils;

@SuppressLint("HandlerLeak")
public class VideoActivity extends Activity implements MediaController.MediaPlayerControl, VideoView.SurfaceCallback {
	
	public static final int RESULT_FAILED = -7;
	
	private static final IntentFilter USER_PRESENT_FILTER = new IntentFilter(Intent.ACTION_USER_PRESENT);
	private static final IntentFilter SCREEN_FILTER = new IntentFilter(Intent.ACTION_SCREEN_ON);
	private static final IntentFilter HEADSET_FILTER = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
	private static final IntentFilter BATTERY_FILTER = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);

	private boolean mCreated = false;
	private boolean mNeedLock;
	private String mDisplayName;
	private String mBatteryLevel;
	private boolean mFromStart;
	private int mLoopCount;
	private boolean mSaveUri;
	private int mParentId;
	private float mStartPos;
	private boolean mEnd = false;
	private String mSubPath;
	private boolean mSubShown;
	private View mViewRoot;
	private VideoView mVideoView;
	private View mVideoLoadingLayout;
	private TextView mVideoLoadingText;
	private View mSubtitleContainer;
	private OutlineTextView mSubtitleText;
	private ImageView mSubtitleImage;
	private Uri mUri;
	private ScreenReceiver mScreenReceiver;
	private HeadsetPlugReceiver mHeadsetPlugReceiver;
	private UserPresentReceiver mUserPresentReceiver;
	private BatteryReceiver mBatteryReceiver;
	private boolean mReceiverRegistered = false;
	private boolean mHeadsetPlaying = false;
	private boolean mCloseComplete = false;
	private boolean mIsHWCodec = false;

	private MediaController mMediaController;
	private PlayerService vPlayer;
	private ServiceConnection vPlayerServiceConnection;
	private Animation mLoadingAnimation;
	private View mLoadingProgressView;
	private Session mSession;

	private ArrayList<String> mVedioList;
	/**
	 * 当前正在看的节目信息
	 */
	private Show currentShow;
	
	/**
	 * 当前正在看的剧集信息
	 */
	private Video currentVideo;
	/**
	 * 作为启动Intent 参数(布尔字段)
	 */
	public static final String INTENT_PARAMATER_VIDEO = "_INTENT_PARAMATER_VIDEO";
	/**
	 * 作为启动Intent 参数(整形字段)
	 */
	public static final String INTENT_PARAMATER_VIDEO_INDEX = "_INTENT_PARAMATER_VIDEO_INDEX";
	
	/**
	 * 作为启动Intent 参数(整形字段)
	 */
	public static final String INTENT_PARAMATER_VIDEO_PATH_INDEX = "_INTENT_PARAMATER_VIDEO_PATH_INDEX";
	
	/**
	 * 作为启动Intent 参数(长整形字段)
	 */
	public static final String INTENT_PARAMATER_VIDEO_PROGRESS = "_INTENT_PARAMATER_VIDEO_PROGRESS";
	/**
	 * 当前播放剧集下标
	 */
	private int video_index;
	
	/**
	 * 当前播放进度
	 */
	private long video_progress;
	
	/**
	 * 当前播放源下标(用于备份源切换功能)
	 */
	private int path_index = 0;
	private MApplication application;

	private String mPath;

	private String splitTitle;

	private boolean minitVideo;
	

	static {
		SCREEN_FILTER.addAction(Intent.ACTION_SCREEN_OFF);
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Log.e("onCreate");
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
		if (!io.vov.vitamio.LibsChecker.checkVitamioLibs(this))
			return;

		mSession = new Session(this);
		vPlayerServiceConnection = new ServiceConnection() {
			@Override
			public void onServiceConnected(ComponentName name, IBinder service) {
				vPlayer = ((PlayerService.LocalBinder) service).getService();
				mServiceConnected = true;
				if (mSurfaceCreated)
					vPlayerHandler.sendEmptyMessage(OPEN_FILE);
			}

			@Override
			public void onServiceDisconnected(ComponentName name) {
				vPlayer = null;
				mServiceConnected = false;
			}
		};
		application = MApplication.getInstance();
		ProgressManager.getInstance().setActivity(this);
		setVolumeControlStream(AudioManager.STREAM_MUSIC);
		parseIntent(getIntent());
		loadView(R.layout.activity_video);
		manageReceivers();

		mCreated = true;
	}

	private void attachMediaController() {
		if (mMediaController != null) {
			mNeedLock = mMediaController.isLocked();
			mMediaController.release();
		}
		mMediaController = new MediaController(this, mNeedLock);
		mMediaController.setMediaPlayer(this);
		mMediaController.setAnchorView(mVideoView.getRootView());
		setFileName();
		setBatteryLevel();
	}

	@Override
	public void onStart() {
		super.onStart();
		Log.e("onStart");
		if (!mCreated)
			return;
		Intent serviceIntent = new Intent(this, PlayerService.class);
		serviceIntent.putExtra("isHWCodec", mIsHWCodec);
		bindService(serviceIntent, vPlayerServiceConnection, Context.BIND_AUTO_CREATE);
	}

	@Override
	public void onResume() {
		super.onResume();
		Log.e("onResume");
		if (!mCreated)
			return;
		if (isInitialized()) {
			KeyguardManager keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE);
			if (!keyguardManager.inKeyguardRestrictedInputMode()) {
				startPlayer();
			}
		} else {
			if (mCloseComplete) {
				reOpen();
			}
		}
	}

	@Override
	public void onPause() {
		super.onPause();
		Log.e("onPause");
		if (!mCreated)
			return;
		ProgressManager.getInstance().cancel();
		try {
			//同步本地数据，保存播放记录
			NDJHBaseDao<Show, Integer> showDao = MApplication.getInstance().getHelper().getShowDao();
			Show show = showDao.queryData("select * from Show where showid = '" + currentShow.getShowid() + "' and sourceName = '"
					+ currentShow.getSourceName() + "';");
			long currPosition = getCurrentPosition();
			if (mMediaController != null && show != null && currPosition > 0) {
				if (currPosition == getDuration()) {
					currPosition = 0;
				}
				currentShow.setLastPlayTime(System.currentTimeMillis());
				currentShow.setLastVideoIndex(video_index);
				currentShow.setLastPathIndex(path_index);
				currentShow.setLastProgress(currPosition);
				show.setLastPlayTime(currentShow.getLastPlayTime());
				show.setLastVideoIndex(video_index);
				show.setLastPathIndex(path_index);
				show.setLastProgress(currPosition);
				showDao.update(show);
			}
			MobclickAgent.onEventEnd(VideoActivity.this, "VIDEO_PLAY_TIME", "{site:\"" + application.getCurrentSource().getSourceThumb()
					+ "\",show:\"" + currentShow.getTitle() + "\",video:\"" + currentVideo.getTitle() + "\"}");
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		if (isInitialized()) {
			savePosition();
			if (vPlayer != null && vPlayer.isPlaying()) {
				stopPlayer();
			}
		}
	}

	@Override
	public void onStop() {
		super.onStop();
		Log.e("onStop");
		if (!mCreated)
			return;
		if (isInitialized()) {
			vPlayer.releaseSurface();
		}
		if (mServiceConnected) {
			unbindService(vPlayerServiceConnection);
			mServiceConnected = false;
		}

	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		Log.e("onDestroy");
		if (!mCreated)
			return;
		
		manageReceivers();
		if (isInitialized() && !vPlayer.isPlaying())
			//完全退出
//			release();
		if (mMediaController != null)
			mMediaController.release();
		
	}

	@Override
	public void onConfigurationChanged(Configuration newConfig) {
		if (isInitialized()) {
			setVideoLayout();
			attachMediaController();
		}

		super.onConfigurationChanged(newConfig);
	}

	@Override
	public void onBackPressed() {
		super.onBackPressed();
	}

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		// http://code.google.com/p/android/issues/detail?id=19917
		outState.putString("WORKAROUND_FOR_BUG_19917_KEY", "WORKAROUND_FOR_BUG_19917_VALUE");
		super.onSaveInstanceState(outState);
	}

	public void showMenu() {

	}

	private void loadView(int id) {
		setContentView(id);
		getWindow().setBackgroundDrawable(null);
		mViewRoot = findViewById(R.id.video_root);
		mVideoView = (VideoView) findViewById(R.id.video);
		mVideoView.initialize(this, this, mIsHWCodec);
		mSubtitleContainer = findViewById(R.id.subtitle_container);
		mSubtitleText = (OutlineTextView) findViewById(R.id.subtitle_text);
		mSubtitleImage = (ImageView) findViewById(R.id.subtitle_image);
		mVideoLoadingText = (TextView) findViewById(R.id.video_loading_text);
		mVideoLoadingLayout = findViewById(R.id.video_loading);
		mLoadingProgressView = mVideoLoadingLayout.findViewById(R.id.video_loading_progress);

		mLoadingAnimation = AnimationUtils.loadAnimation(VideoActivity.this, R.anim.loading_rotate);
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
	}

	private void parseIntent(Intent i) {
		currentShow = application.getCurrentShow();
		minitVideo = i.getBooleanExtra(INTENT_PARAMATER_VIDEO, false);
		if (minitVideo) {
			video_index = i.getIntExtra(INTENT_PARAMATER_VIDEO_INDEX, 0);
			path_index = i.getIntExtra(INTENT_PARAMATER_VIDEO_PATH_INDEX, 0);
			video_progress = i.getLongExtra(INTENT_PARAMATER_VIDEO_PROGRESS, -1);
			initVideoData(video_index, path_index, video_progress);
			mFromStart = i.getBooleanExtra("fromStart", false);
		} else {
			if (i.getExtras() != null) {
				mVedioList = i.getExtras().getStringArrayList("vedioList");
			}

			if (mVedioList == null || mVedioList.size() == 0) {
				Uri dat = /* IntentHelper.getIntentUri(i) */i.getData();
				if (dat == null)
					resultFinish(RESULT_FAILED);

				String datString = dat.toString();
				if (!datString.equals(dat.toString()))
					dat = Uri.parse(datString);

				mUri = dat;
			} else {
				mUri = Uri.parse(mVedioList.get(0));
			}

			mNeedLock = i.getBooleanExtra("lockScreen", false);
			mDisplayName = i.getStringExtra("displayName");
			mFromStart = i.getBooleanExtra("fromStart", false);
			mSaveUri = i.getBooleanExtra("saveUri", true);
			mStartPos = i.getFloatExtra("startPosition", -1.0f);
			mLoopCount = i.getIntExtra("loopCount", 1);
			mParentId = i.getIntExtra("parentId", 0);
			mSubPath = i.getStringExtra("subPath");
			mSubShown = i.getBooleanExtra("subShown", true);
			mIsHWCodec = i.getBooleanExtra("hwCodec", false);
			Log.i("L: %b, N: %s, S: %b, P: %f, LP: %d", mNeedLock, mDisplayName, mFromStart, mStartPos, mLoopCount);
		}
	}

	/**
	 * 初始化视频组件所需数据
	 * @param video_index
	 * @param video_progress
	 */
	private void initVideoData(int video_index, int path_index, long video_progress) {
		if (video_index >= 0 && currentShow != null && video_index < currentShow.getVideos().size()) {
			currentVideo = currentShow.getVideos().get(video_index);
		}
		if(currentVideo != null){
			String quality = currentShow.getCurrentQuality();
			mDisplayName = currentVideo.getTitle() == null ? currentShow.getTitle() : currentVideo.getTitle();
			mPath = getPlayPath(quality, path_index);
		} 
		try {
			currentShow.setLastVideoIndex(video_index);
			currentShow.setLastPathIndex(path_index);
			NDJHBaseDao<Show, Integer> showDao = MApplication.getInstance().getHelper().getShowDao();
			Show show = showDao.queryData("select * from Show where showid = '" + currentShow.getShowid() + "' and sourceName = '"
					+ currentShow.getSourceName() + "';");
			if (show != null) {
				show.setLastVideoIndex(video_index );
				show.setLastPathIndex(path_index);
				showDao.update(show);
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}
		if (!StringUtil.isNull(mPath)) {
			mUri = Uri.parse(mPath);
//			initVideoPlayer(video_progress, 0);
//			new VPlayerInitialTask().execute(new Long[]{video_progress,(long) 0});
		} else {
			VideoPathLoader videoPathLoader = new VideoPathLoader();
			videoPathLoader.execute(currentVideo);
		}
	}
	/**
	 * 从currentVideo取得视频播放源地址
	 * @param quality 清晰度
	 * @param path_index 源列表
	 * @return 如果没找到，则默认第一条
	 */
	private String getPlayPath(String quality, int path_index) {
		if (StringUtil.isNull(currentVideo.getVideoPaths())) {
			return null;
		}
		if(!StringUtil.isNull(currentVideo.getVideoPaths().get(0).getUrlSplits())){
			//分段视频播放
			for (int i = 0; i < currentVideo.getVideoPaths().size(); i++) {
				VideoPath videoPath = (VideoPath) currentVideo.getVideoPaths().get(i);
				if (!StringUtil.isNull(videoPath.getUrlSplits()) && videoPath.getQuality().equals(quality)) {
					if (path_index >= 0 && videoPath.getUrlSplits().size() > path_index) {
						splitTitle = "分段: " + (path_index + 1) + "/" + videoPath.getUrlSplits().size();
						mDisplayName = mDisplayName + "   " +splitTitle;
						return videoPath.getUrlSplits().get(path_index);
					} else {
						splitTitle = "分段: " + (path_index + 1) + "/" + videoPath.getUrlSplits().size();
						mDisplayName = mDisplayName + "   " +splitTitle;
						return videoPath.getUrlSplits().get(0);
					}
				}
			}
		}else{
			for (int i = 0; i < currentVideo.getVideoPaths().size(); i++) {
				VideoPath videoPath = (VideoPath) currentVideo.getVideoPaths().get(i);
				if (!StringUtil.isNull(videoPath.getUrl()) && videoPath.getQuality().equals(quality)) {
					if (path_index >= 0 && videoPath.getUrl().size() > path_index) {
						return videoPath.getUrl().get(path_index);
					} else {
						return videoPath.getUrl().get(0);
					}
				}
			}
			if (!StringUtil.isNull(currentVideo.getVideoPaths().get(0).getUrl())) {
				return currentVideo.getVideoPaths().get(0).getUrl().get(0);
			}
		}
		
		
		return null;
	}
	/**
	 * 线程路径
	 * @author Administrator
	 *
	 */
	private class VideoPathLoader extends AsyncTask<Video, Integer, Boolean> {
		
		@Override
		protected Boolean doInBackground(Video... params) {
			try {
				List<VideoPath> videoPaths = application.getCurrentSource().getVideoPaths(params[0]);
				if (videoPaths != null && videoPaths.size() >= 0) {
					String quality = currentShow.getCurrentQuality();
					mPath = getPlayPath(quality, path_index);
					System.err.println("获取播放地址: " + mPath);
					if(!StringUtil.isNull(mPath)){
						mUri = Uri.parse(mPath);
						return true;
					}
				}	
			} catch (Exception e) {
				e.printStackTrace();
			}
			return false;
		}
		
		@Override
		protected void onCancelled() {
			// TODO Auto-generated method stub
			ProgressManager.getInstance().cancel();
		}
		
		@Override
		protected void onPostExecute(Boolean result) {
			//TODO 返回HTML页面的内容
			if(result){
//				initVideoPlayer(video_progress, 0);
				new VPlayerInitialTask().execute(new Long[]{video_progress,(long) 0});

			} else {
				// TODO 错误信息处理
//				Toast.makeText(PlayActivity.this, "获取视频播放地址失败,", Toast.LENGTH_SHORT).show();
				runOnUiThread(new Runnable() {
					public void run() {
						showAlertDialog("警告", "非常抱歉,获取视频播放地址失败!", onCancelListener);
					}
				});
			}
			ProgressManager.getInstance().cancel();
		}
		
		@Override
		protected void onPreExecute() {
			//TODO 任务启动，可以在这里显示一个对话框，这里简单处理
			ProgressManager.getInstance().showProcessDialog("加载中...");
		}
		
		@Override
		protected void onProgressUpdate(Integer... values) {
			 //TODO 更新进度
			super.onProgressUpdate(values);
		}

	};
	
	/**
	 * 显示消息提示框,然后只给用户确定按钮
	 * @param title 
	 * @param message
	 */
	protected void showAlertDialog(String title,String message, OnCancelListener onCancelListener) {
		try {
			if(isFinishing()){
				return;
			}
			StandardAlertDialog.Builder ndAlertDialog = new StandardAlertDialog.Builder(VideoActivity.this);
			ndAlertDialog.setTitle(title);
			ndAlertDialog.setMessage(message);
			ndAlertDialog.setPositiveButton("确定", new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog, int which) {
					dialog.cancel();
				}
			});
			StandardAlertDialog dialog = ndAlertDialog.create();
			dialog.setOnCancelListener(onCancelListener);
			dialog.show();
		} catch (Exception e) {
			// TODO: handle exception
		}
		
	}
	OnCancelListener onCancelListener =  new OnCancelListener() {
		@Override
		public void onCancel(DialogInterface dialog) {
			System.err.println("onCancel");
			finish();
		}
	};
	
	private class VPlayerInitialTask extends AsyncTask<Long, Object, Object> {

		@Override
		protected void onPreExecute() {
			try {
//				VideoActivity.this.mVideoView.setVisibility(8);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		@Override
		protected Object doInBackground(Long... params) {
			try {
				if (!vPlayer.initialize(mUri, mDisplayName, mSaveUri, params[0] == null?getStartPosition():params[0], vPlayerListener, mParentId, mIsHWCodec)) {
					VideoActivity.this.mPlayerOK = true;
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			return null;
		}

		@Override
		protected void onPostExecute(Object result) {
			try {
				if (VideoActivity.this.mPlayerOK) {
					VideoActivity.this.mVideoView.setVisibility(0);
					VideoActivity.this.mPlayerOK = false;
				}
				return;
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		

	}
	
	private void manageReceivers() {
		if (!mReceiverRegistered) {
			mScreenReceiver = new ScreenReceiver();
			registerReceiver(mScreenReceiver, SCREEN_FILTER);
			mUserPresentReceiver = new UserPresentReceiver();
			registerReceiver(mUserPresentReceiver, USER_PRESENT_FILTER);
			mBatteryReceiver = new BatteryReceiver();
			registerReceiver(mBatteryReceiver, BATTERY_FILTER);
			mHeadsetPlugReceiver = new HeadsetPlugReceiver();
			registerReceiver(mHeadsetPlugReceiver, HEADSET_FILTER);
			mReceiverRegistered = true;
		} else {
			try {
				if (mScreenReceiver != null)
					unregisterReceiver(mScreenReceiver);
				if (mUserPresentReceiver != null)
					unregisterReceiver(mUserPresentReceiver);
				if (mHeadsetPlugReceiver != null)
					unregisterReceiver(mHeadsetPlugReceiver);
				if (mBatteryReceiver != null)
					unregisterReceiver(mBatteryReceiver);
			} catch (IllegalArgumentException e) {
			}
			mReceiverRegistered = false;
		}
	}

	private void setFileName() {
		if (mUri != null) {
			String name = null;
			if (mUri.getScheme() == null || mUri.getScheme().equals("file"))
				name = FileUtils.getName(mUri.toString());
			else
				name = mUri.getLastPathSegment();
			if (name == null)
				name = "null";
			if (mDisplayName == null)
				mDisplayName = name;
			mMediaController.setFileName(mDisplayName);
		}
	}

	private void applyResult(int resultCode) {
		vPlayerHandler.removeMessages(BUFFER_PROGRESS);
		Intent i = new Intent();
		i.putExtra("filePath", mUri.toString());
		if (isInitialized()) {
			i.putExtra("position", (double) vPlayer.getCurrentPosition() / vPlayer.getDuration());
			i.putExtra("duration", vPlayer.getDuration());
			savePosition();
		}
		switch (resultCode) {
		case RESULT_FAILED:
			ToastHelper.showToast(this, Toast.LENGTH_LONG, R.string.video_cannot_play);
			break;
		case RESULT_CANCELED:
		case RESULT_OK:
			break;
		}
		setResult(resultCode, i);
	}

	private void resultFinish(int resultCode) {
		applyResult(resultCode);
//		if (UIUtils.hasICS() && resultCode != RESULT_FAILED) {
//			android.os.Process.killProcess(android.os.Process.myPid());
//		} else {
			finish();
//		}
	}

	private void release() {
		if (vPlayer != null) {
			if (UIUtils.hasICS()) {
				android.os.Process.killProcess(android.os.Process.myPid());
			} else {
				vPlayer.release();
				vPlayer.releaseContext();
			}
		}
	}

	private void reOpen(Uri path, String name, boolean fromStart) {
		if (isInitialized()) {
			savePosition();
			vPlayer.release();
			vPlayer.releaseContext();
		}
		Intent i = getIntent();
		i.putExtra("lockScreen", mMediaController != null ? mMediaController.isLocked() : false);
		i.putExtra("startPosition", (float) mSession.getDouble(mUri + VP.SESSION_LAST_POSITION_SUFIX, 7.7f));
		i.putExtra("fromStart", fromStart);
		i.putExtra("displayName", name);
		i.setData(path);
		parseIntent(i);
		mUri = path;
		if (mViewRoot != null)
			mViewRoot.invalidate();
		mOpened.set(false);
	}

	public void reOpen() {
		reOpen(mUri, mDisplayName, false);
	}

	protected void startPlayer() {
		if (isInitialized() && mScreenReceiver.screenOn && !vPlayer.isBuffering()) {
			Log.i("VideoActivity#startPlayer");
			if (!vPlayer.isPlaying()) {
				vPlayer.start();
			}
		}
	}

	protected void stopPlayer() {
		if (isInitialized()) {
			vPlayer.stop();
		}
	}

	private void setBatteryLevel() {
		if (mMediaController != null)
			mMediaController.setBatteryLevel(mBatteryLevel);
	}

	private class BatteryReceiver extends BroadcastReceiver {
		@Override
		public void onReceive(Context context, Intent intent) {
			int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
			int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100);
			int percent = scale > 0 ? level * 100 / scale : 0;
			if (percent > 100)
				percent = 100;
			mBatteryLevel = String.valueOf(percent) + "%";
			setBatteryLevel();
		}
	}

	private class UserPresentReceiver extends BroadcastReceiver {
		@Override
		public void onReceive(Context context, Intent intent) {
			if (isRootActivity()) {
				startPlayer();
			}
		}
	}

	private boolean isRootActivity() {
		ActivityManager activity = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
		return activity.getRunningTasks(1).get(0).topActivity.flattenToString().endsWith("io.vov.vitamio.activity.VideoActivity");
	}

	public class HeadsetPlugReceiver extends BroadcastReceiver {
		@Override
		public void onReceive(Context context, Intent intent) {
			if (intent != null && intent.hasExtra("state")) {
				int state = intent.getIntExtra("state", -1);
				if (state == 0) {
					mHeadsetPlaying = isPlaying();
					stopPlayer();
				} else if (state == 1) {
					if (mHeadsetPlaying)
						startPlayer();
				}
			}
		};
	}

	private class ScreenReceiver extends BroadcastReceiver {
		private boolean screenOn = true;

		@Override
		public void onReceive(Context context, Intent intent) {
			if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
				screenOn = false;
				stopPlayer();
			} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
				screenOn = true;
			}
		}
	}

	private void loadVPlayerPrefs() {
		if (!isInitialized())
			return;
		vPlayer.setBuffer(VP.DEFAULT_BUF_SIZE);
		vPlayer.setVideoQuality(VP.DEFAULT_VIDEO_QUALITY);
		vPlayer.setDeinterlace(VP.DEFAULT_DEINTERLACE);
		vPlayer.setVolume(VP.DEFAULT_STEREO_VOLUME, VP.DEFAULT_STEREO_VOLUME);
		vPlayer.setSubEncoding(VP.DEFAULT_SUB_ENCODING);
		MarginLayoutParams lp = (MarginLayoutParams) mSubtitleContainer.getLayoutParams();
		lp.bottomMargin = (int) VP.DEFAULT_SUB_POS;
		mSubtitleContainer.setLayoutParams(lp);
		vPlayer.setSubShown(mSubShown);
		setTextViewStyle(mSubtitleText);
		if (!TextUtils.isEmpty(mSubPath))
			vPlayer.setSubPath(mSubPath);
		if (mVideoView != null && isInitialized())
			setVideoLayout();
	}
	
	private void setTextViewStyle(OutlineTextView v) {
		v.setTextColor(VP.DEFAULT_SUB_COLOR);
		v.setTypeface(VP.getTypeface(VP.DEFAULT_TYPEFACE_INT), VP.DEFAULT_SUB_STYLE);
		v.setShadowLayer(VP.DEFAULT_SUB_SHADOWRADIUS, 0, 0, VP.DEFAULT_SUB_SHADOWCOLOR);
	}

	private boolean isInitialized() {
		return (mCreated && vPlayer != null && vPlayer.isInitialized());
	}
	
	private Handler mSubHandler = new Handler() {
		Bundle data;
		String text;
		byte[] pixels;
		int width = 0, height = 0;
		Bitmap bm = null;
		int oldType = SUBTITLE_TEXT;

		@Override
		public void handleMessage(Message msg) {
			data = msg.getData();
			switch (msg.what) {
			case SUBTITLE_TEXT:
				if (oldType != SUBTITLE_TEXT) {
					mSubtitleImage.setVisibility(View.GONE);
					mSubtitleText.setVisibility(View.VISIBLE);
					oldType = SUBTITLE_TEXT;
				}
				text = data.getString(VP.SUB_TEXT_KEY);
				mSubtitleText.setText(text == null ? "" : text.trim());
				break;
			case SUBTITLE_BITMAP:
				if (oldType != SUBTITLE_BITMAP) {
					mSubtitleText.setVisibility(View.GONE);
					mSubtitleImage.setVisibility(View.VISIBLE);
					oldType = SUBTITLE_BITMAP;
				}
				pixels = data.getByteArray(VP.SUB_PIXELS_KEY);
				if (bm == null || width != data.getInt(VP.SUB_WIDTH_KEY) || height != data.getInt(VP.SUB_HEIGHT_KEY)) {
					width = data.getInt(VP.SUB_WIDTH_KEY);
					height = data.getInt(VP.SUB_HEIGHT_KEY);
					bm = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
				}
				if (pixels != null)
					bm.copyPixelsFromBuffer(ByteBuffer.wrap(pixels));
				mSubtitleImage.setImageBitmap(bm);
				break;
			}
		}
	};

	private AtomicBoolean mOpened = new AtomicBoolean(Boolean.FALSE);
	private boolean mSurfaceCreated = false;
	private boolean mServiceConnected = false;
	private Object mOpenLock = new Object();
	private static final int OPEN_FILE = 0;
	private static final int OPEN_START = 1;
	private static final int OPEN_SUCCESS = 2;
	private static final int OPEN_FAILED = 3;
	private static final int HW_FAILED = 4;
	private static final int LOAD_PREFS = 5;
	private static final int BUFFER_START = 11;
	private static final int BUFFER_PROGRESS = 12;
	private static final int BUFFER_COMPLETE = 13;
	private static final int CLOSE_START = 21;
	private static final int CLOSE_COMPLETE = 22;
	private static final int SUBTITLE_TEXT = 0;
	private static final int SUBTITLE_BITMAP = 1;
	private Handler vPlayerHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case OPEN_FILE:
				synchronized (mOpenLock) {
					if (!mOpened.get() && vPlayer != null) {
						mOpened.set(true);
						vPlayer.setVPlayerListener(vPlayerListener);
						if (vPlayer.isInitialized())
							mUri = vPlayer.getUri();

						if (mVideoView != null)
							vPlayer.setDisplay(mVideoView.getHolder());
						if (mUri != null)
							vPlayer.initialize(mUri, mDisplayName, mSaveUri, getStartPosition(), vPlayerListener, mParentId, mIsHWCodec);
					}
				}
				break;
			case OPEN_START:
				mVideoLoadingText.setText(R.string.video_layout_loading);
				setVideoLoadingLayoutVisibility(View.VISIBLE);
				break;
			case OPEN_SUCCESS:
				loadVPlayerPrefs();
				setVideoLoadingLayoutVisibility(View.GONE);
				setVideoLayout();
				vPlayer.start();
				attachMediaController();
				break;
			case OPEN_FAILED:
				resultFinish(RESULT_FAILED);
				break;
			case BUFFER_START:
				setVideoLoadingLayoutVisibility(View.VISIBLE);
				vPlayerHandler.sendEmptyMessageDelayed(BUFFER_PROGRESS, 1000);
				break;
			case BUFFER_PROGRESS:
				if (vPlayer.getBufferProgress() >= 100) {
					setVideoLoadingLayoutVisibility(View.GONE);
				} else {
					mVideoLoadingText.setText(getString(R.string.video_layout_buffering_progress, vPlayer.getBufferProgress()));
					vPlayerHandler.sendEmptyMessageDelayed(BUFFER_PROGRESS, 1000);
					stopPlayer();
				}
				break;
			case BUFFER_COMPLETE:
				setVideoLoadingLayoutVisibility(View.GONE);
				vPlayerHandler.removeMessages(BUFFER_PROGRESS);
				break;
			case CLOSE_START:
				mVideoLoadingText.setText(R.string.closing_file);
				setVideoLoadingLayoutVisibility(View.VISIBLE);
				break;
			case CLOSE_COMPLETE:
				mCloseComplete = true;
				break;
			case HW_FAILED:
				if (mVideoView != null) {
					mVideoView.setVisibility(View.GONE);
					mVideoView.setVisibility(View.VISIBLE);
					mVideoView.initialize(VideoActivity.this, VideoActivity.this, false);
				}
				break;
			case LOAD_PREFS:
				loadVPlayerPrefs();
				break;
			}
		}
	};

	private void setVideoLoadingLayoutVisibility(int visibility) {
		if (mVideoLoadingLayout != null && mLoadingProgressView != null) {
			if (visibility == View.VISIBLE)
				mLoadingProgressView.startAnimation(mLoadingAnimation);
			mVideoLoadingLayout.setVisibility(visibility);
		}
	}

	private PlayerService.VPlayerListener vPlayerListener = new PlayerService.VPlayerListener() {
		@Override
		public void onHWRenderFailed() {
			if (Build.VERSION.SDK_INT < 11 && mIsHWCodec) {
				vPlayerHandler.sendEmptyMessage(HW_FAILED);
				vPlayerHandler.sendEmptyMessageDelayed(HW_FAILED, 200);
			}
		}

		@Override
		public void onSubChanged(String sub) {
			Message msg = new Message();
			Bundle b = new Bundle();
			b.putString(VP.SUB_TEXT_KEY, sub);
			msg.setData(b);
			msg.what = SUBTITLE_TEXT;
			mSubHandler.sendMessage(msg);
		}

		@Override
		public void onSubChanged(byte[] pixels, int width, int height) {
			Message msg = new Message();
			Bundle b = new Bundle();
			b.putByteArray(VP.SUB_PIXELS_KEY, pixels);
			b.putInt(VP.SUB_WIDTH_KEY, width);
			b.putInt(VP.SUB_HEIGHT_KEY, height);
			msg.setData(b);
			msg.what = SUBTITLE_BITMAP;
			mSubHandler.sendMessage(msg);
		}

		@Override
		public void onOpenStart() {
			vPlayerHandler.sendEmptyMessage(OPEN_START);
		}

		@Override
		public void onOpenSuccess() {
			vPlayerHandler.sendEmptyMessage(OPEN_SUCCESS);
		}

		@Override
		public void onOpenFailed() {
			vPlayerHandler.sendEmptyMessage(OPEN_FAILED);
		}

		@Override
		public void onBufferStart() {
			vPlayerHandler.sendEmptyMessage(BUFFER_START);
			stopPlayer();
		}

		@Override
		public void onBufferComplete() {
			Log.i("VideoActivity#onBufferComplete " + vPlayer.needResume());
			vPlayerHandler.sendEmptyMessage(BUFFER_COMPLETE);
			if (vPlayer != null && !vPlayer.needResume()&& !mPlayerStop)
				startPlayer();
		}

		@Override
		public void onPlaybackComplete() {
//			mEnd = true;
			if (mLoopCount == 0 || mLoopCount-- > 1) {
				// 视频播放结束，这里需要做事情
				
				if (!StringUtil.isNull(currentVideo.getVideoPaths()) &&!StringUtil.isNull(currentVideo.getVideoPaths().get(0).getUrlSplits()) && currentVideo.getVideoPaths().get(0).getUrlSplits().size() > (path_index + 1)) {
					Log.e("path_index++"+path_index);
					path_index++;
					initVideoData(video_index, path_index, 0);
					vPlayer.release();
					vPlayer.releaseContext();
					new VPlayerInitialTask().execute(new Long[]{video_progress,(long) 0});
				}else if (video_index >= 0 && video_index < currentShow.getVideos().size() - 1) {
					path_index = 0;
					video_index++;
					initVideoData(video_index, path_index, 0);
					vPlayer.release();
					vPlayer.releaseContext();
					new VPlayerInitialTask().execute(new Long[]{video_progress,(long) 0});
				} else {
//					mVideoView.refreshDrawableState();
					finish();
				}
//				vPlayer.start();
//				vPlayer.seekTo(0);
				
//				Intent i = getIntent();
//				i.setData(Uri.parse(mVedioList.get(mVedioList.size() - mLoopCount -1)));
//				parseIntent(i);
//				vPlayer.stop();
//				mUri = Uri.parse(mVedioList.get(mVedioList.size() - mLoopCount));
				//mDisplayName = mDisplayName + "  (" + (mVedioList.size() - mLoopCount + 1 ) + "/" + mVedioList.size() + ")";
//				vPlayer.initialize(mUri, mDisplayName, mSaveUri, getStartPosition(), vPlayerListener, mParentId, mIsHWCodec);
//				new VPlayerInitialTask().execute(new Boolean[0]);
			} else {
				resultFinish(RESULT_OK);
			
				}
			
		}

		@Override
		public void onCloseStart() {
			vPlayerHandler.sendEmptyMessage(CLOSE_START);
		}

		@Override
		public void onCloseComplete() {
			vPlayerHandler.sendEmptyMessage(CLOSE_COMPLETE);
		}

		@Override
		public void onVideoSizeChanged(int width, int height) {
			if (mVideoView != null) {
				setVideoLayout();
			}
		}

		@Override
		public void onDownloadRateChanged(int kbPerSec) {
			if (!Media.isNative(mUri.toString()) && mMediaController != null) {
				mMediaController.setDownloadRate(String.format("%dKB/s", kbPerSec));
			}
		}

//		@Override
//		public void onPlayback() {
//			reOpen();
//		}

	};

	private int mVideoMode = VideoView.VIDEO_LAYOUT_SCALE;

	public boolean mPlayerOK;

	private boolean mPlayerStop;


	private void setVideoLayout() {
		mVideoView.setVideoLayout(mVideoMode, VP.DEFAULT_ASPECT_RATIO, vPlayer.getVideoWidth(), vPlayer.getVideoHeight(), vPlayer.getVideoAspectRatio());
	}

	private void savePosition() {
		if (mSession != null && vPlayer != null && mUri != null) {
			mSession.put(mUri.toString(), StringHelper.generateTime((int) (0.5 + vPlayer.getCurrentPosition())) + " / " + StringHelper.generateTime(vPlayer.getDuration()));
			if (mEnd)
				mSession.put(mUri + VP.SESSION_LAST_POSITION_SUFIX, 1.0f);
			else
				mSession.put(mUri + VP.SESSION_LAST_POSITION_SUFIX, (float) (vPlayer.getCurrentPosition() / (double) vPlayer.getDuration()));
		}
	}

	private float getStartPosition() {
		if (mFromStart)
			return 1.1f;
		if (mStartPos <= 0.0f || mStartPos >= 1.0f)
			return mSession.getFloat(mUri + VP.SESSION_LAST_POSITION_SUFIX, 7.7f);
		return mStartPos;
	}

	@Override
	public int getBufferPercentage() {
		if (isInitialized())
			return (int) (vPlayer.getBufferProgress() * 100);
		return 0;
	}

	@Override
	public long getCurrentPosition() {
		if (isInitialized())
			return vPlayer.getCurrentPosition();
		return (long) (getStartPosition() * vPlayer.getDuration());
	}

	@Override
	public long getDuration() {
		if (isInitialized())
			return vPlayer.getDuration();
		return 0;
	}

	@Override
	public boolean isPlaying() {
		if (isInitialized())
			return vPlayer.isPlaying();
		return false;
	}

	@Override
	public void pause() {
		if (isInitialized()){
			vPlayer.stop();
			mPlayerStop = true;
		}
	}

	@Override
	public void seekTo(long arg0) {
		if (isInitialized())
			vPlayer.seekTo((float) ((double) arg0 / vPlayer.getDuration()));
	}

	@Override
	public void start() {
		if (isInitialized()){
			vPlayer.start();
			mPlayerStop = false;
		}
	}

	@Override
	public void previous() {
	}

	@Override
	public void next() {
	}

	private static final int VIDEO_MAXIMUM_HEIGHT = 2048;
	private static final int VIDEO_MAXIMUM_WIDTH = 2048;

	@Override
	public float scale(float scaleFactor) {
		float userRatio = VP.DEFAULT_ASPECT_RATIO;
		int videoWidth = vPlayer.getVideoWidth();
		int videoHeight = vPlayer.getVideoHeight();
		float videoRatio = vPlayer.getVideoAspectRatio();
		float currentRatio = mVideoView.mVideoHeight / (float) videoHeight;

		currentRatio += (scaleFactor - 1);
		if (videoWidth * currentRatio >= VIDEO_MAXIMUM_WIDTH)
			currentRatio = VIDEO_MAXIMUM_WIDTH / (float) videoWidth;

		if (videoHeight * currentRatio >= VIDEO_MAXIMUM_HEIGHT)
			currentRatio = VIDEO_MAXIMUM_HEIGHT / (float) videoHeight;

		if (currentRatio < 0.5f)
			currentRatio = 0.5f;

		mVideoView.mVideoHeight = (int) (videoHeight * currentRatio);
		mVideoView.setVideoLayout(mVideoMode, userRatio, videoWidth, videoHeight, videoRatio);
		return currentRatio;
	}

	@SuppressLint("SimpleDateFormat")
	@Override
	public void snapshot() {
		if (!FileHelper.sdAvailable()) {
			ToastHelper.showToast(this, R.string.file_explorer_sdcard_not_available);
		} else {
			Uri imgUri = null;
			Bitmap bitmap = vPlayer.getCurrentFrame();
			if (bitmap != null) {
				File screenshotsDirectory = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + VP.SNAP_SHOT_PATH);
				if (!screenshotsDirectory.exists()) {
					screenshotsDirectory.mkdirs();
				}

				File savePath = new File(screenshotsDirectory.getPath() + "/" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + ".jpg");
				if (BitmapHelper.saveBitmapToFile(bitmap, savePath.getPath())) {
					imgUri = Uri.fromFile(savePath);
				}
			}
			if (imgUri != null) {
				sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, imgUri));
				ToastHelper.showToast(this, Toast.LENGTH_LONG, getString(R.string.video_screenshot_save_in, imgUri.getPath()));
			} else {
				ToastHelper.showToast(this, R.string.video_screenshot_failed);
			}
		}
	}

	@Override
	public void toggleVideoMode(int mode) {
		mVideoMode = mode;
		setVideoLayout();
	}

	@Override
	public void stop() {
		onBackPressed();
	}

	@Override
	public long goForward() {
		return 0;
	}

	@Override
	public long goBack() {
		return 0;
	}

	@Override
	public void removeLoadingView() {
		mVideoLoadingLayout.setVisibility(View.GONE);
	}

	@Override
	public void onSurfaceCreated(SurfaceHolder holder) {
		Log.i("onSurfaceCreated");
		mSurfaceCreated = true;
		if (mServiceConnected)
			vPlayerHandler.sendEmptyMessage(OPEN_FILE);
		if (vPlayer != null)
			vPlayer.setDisplay(holder);
	}

	@Override
	public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
		if (vPlayer != null) {
			vPlayer.setDisplay(holder);
			setVideoLayout();
		}
	}

	@Override
	public void onSurfaceDestroyed(SurfaceHolder holder) {
		Log.i("onSurfaceDestroyed");
		if (vPlayer != null && vPlayer.isInitialized()) {
			if (vPlayer.isPlaying()) {
				vPlayer.stop();
				vPlayer.setState(PlayerService.STATE_NEED_RESUME);
			}
			vPlayer.releaseSurface();
			if (vPlayer.needResume())
				vPlayer.start();
		}
	}
	
	
}
